﻿namespace MEF_Test.Bricks.MediaBrowser
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;

    using MEF_Test.Contracts;

    // FIXME : Move all this code out of the codebehind !!!!!!!

    /// <summary>
    /// Interaction logic for MediaBrowser.xaml
    /// </summary>
    public partial class MediaBrowser : UserControl
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="MediaBrowser"/> class.
        /// </summary>
        public MediaBrowser()
        {
            // Register navigationCommands so e can use key gestures and keyboard special keys to browse back.
            CommandBindings.Add(
                new CommandBinding(
                    NavigationCommands.BrowseBack,
                    (o, e) => ((MediaBrowser)e.Source).BrowsingProvider.GoToParentNode(),
                (o, e) => e.CanExecute = !((MediaBrowser)o).BrowsingProvider.IsRoot));
            ViewModel = new MediaBrowserViewModel();
            InitializeComponent();
        }

        /// <summary>
        /// Gets or sets the item template selector.
        /// </summary>
        /// <value>The item template selector.</value>
        public DataTemplateSelector ItemTemplateSelector
        {
            get { return (DataTemplateSelector)GetValue(ItemTemplateSelectorProperty); }
            set { SetValue(ItemTemplateSelectorProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ItemTemplateSelector.  This enables animation, styling, binding, etc...
        /// <summary>
        /// The dependency property exposing the <see cref="ItemTemplateSelector"/> for the instance. 
        /// </summary>
        public static readonly DependencyProperty ItemTemplateSelectorProperty =
            DependencyProperty.Register("ItemTemplateSelector", typeof(DataTemplateSelector), typeof(MediaBrowser), new UIPropertyMetadata(null));
        


        // when navigating : fetch the new datas from the model.
        public void BrowserElement_DoubleClick(object sender, MouseButtonEventArgs e)
        {
            var node = (IBrowserNodeViewModel)((ListBoxItem)sender).Content;

            // If the current Node is a directory or an element whose content can be browsed.
            if (node.FileHandler.CanHaveChildren)
            {

                BrowsingProvider.GoToNode(node);
            }

        }

        /// <summary>
        /// Gets or sets the browsing provider.
        /// </summary>
        /// <value>The browsing provider.</value>
        /// <remarks>Note the PropertyChangedCallback : if the model is changed, make sure the children to be displayed match the provider's current node children !</remarks>
        public MediaBrowsingProviderBase BrowsingProvider
        {
            get { return (MediaBrowsingProviderBase)GetValue(BrowsingProviderProperty); }
            set { SetValue(BrowsingProviderProperty, value); }
        }


        /// <summary>
        /// The dependency property to expose the <see cref="BrowsingProvider"/>.
        /// </summary>
        public static readonly DependencyProperty BrowsingProviderProperty =
            DependencyProperty.Register(
                "BrowsingProvider",
                typeof(MediaBrowsingProviderBase),
                typeof(MediaBrowser),
                new UIPropertyMetadata(
                    new PropertyChangedCallback(
                        (o, e) =>
                        {
                            var me = (MediaBrowser)o;

                            // we've got a new provider : every time it raises a CurrentChildrenChanged event, we'll need to tell the ViewModel !

                            // Design question : does it respect the MVVM pattern if we do it that way ? this is a UC, not a window : it exposes DP and needs to work with it. Should the BrowsingProvided be copied to the ViewModel and only access it from there ? and the DP would be just here to expose it to be used declaratively from XAML ?
                            me.BrowsingProvider.CurrentChildrenChanged += me.BrowsingProvider_CurrentChildrenChanged;

                            // Force to refresh the children (otherwise, the children list will be empty, as the BrowsingProvider is new)
                            ((MediaBrowsingProviderBase)e.NewValue).InvalidateChildren();
                        })));

        private void BrowsingProvider_CurrentChildrenChanged(object sender, CurrentChildrenChangedEventArgs e)
        {
            // Here, we have to be carefull : since the event can be initiated in response to a FileSystemWatcher event, we have to make sure we 
            // mess with Dependency Properties on the correct (UI) thread. (FileSystemWatcher are monitoring the file system on a separate thread)
            if (Dispatcher.CheckAccess())
            {
               ViewModel.Children = new ObservableCollection<IBrowserNodeViewModel>(e.Children);
            }
            else
            {
                Dispatcher.BeginInvoke(
                    new Action<IEnumerable<IBrowserNodeViewModel>>(
                        c =>
                        {
                            ViewModel.Children = new ObservableCollection<IBrowserNodeViewModel>(c);
                        }),
                    e.Children);
            }
        }

        public MediaBrowserViewModel ViewModel
        {
            get { return (MediaBrowserViewModel)GetValue(ViewModelProperty); }
            set { SetValue(ViewModelProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ViewModel.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ViewModelProperty =
            DependencyProperty.Register("ViewModel", typeof(MediaBrowserViewModel), typeof(MediaBrowser), new UIPropertyMetadata(null));



    }
}